#include "DoxyBlocks.h"
#include <sdk.h>
#include <M_Code_StyledTextCtrl.h>
#include <configurationpanel.h>
#include <projectloader_hooks.h>
#include <tinywxuni.h>
#include <wx/tokenzr.h>
#include <wx/textfile.h>
#include "ConfigPanel.h"
#include "DoxyBlocksLogger.h"

namespace {
  PluginRegistrant<DoxyBlocks> reg( wxT( "DoxyBlocks" ) );
}

const long ID_TB_WIZARD = wxNewId();
const long ID_TB_EXTRACTPROJECT = wxNewId();
const long ID_TB_BLOCKCOMMENT = wxNewId();
const long ID_TB_LINECOMMENT = wxNewId();
const long ID_TB_RUNHTML = wxNewId();
const long ID_TB_RUNCHM = wxNewId();
const long ID_TB_CONFIG = wxNewId();
const long ID_MENU_DOXYBLOCKS = wxNewId();
const long ID_MENU_DOXYWIZARD = wxNewId();
const long ID_MENU_EXTRACTPROJECT = wxNewId();
const long ID_MENU_BLOCKCOMMENT = wxNewId();
const long ID_MENU_LINECOMMENT = wxNewId();
const long ID_MENU_RUNHTML = wxNewId();
const long ID_MENU_RUNCHM = wxNewId();
const long ID_MENU_CONFIG = wxNewId();
const long ID_MENU_SAVE_TEMPLATE  = wxNewId();
const long ID_MENU_LOAD_TEMPLATE  = wxNewId();

BEGIN_EVENT_TABLE( DoxyBlocks, M_Code_Plugin )
  EVT_UPDATE_UI( ID_TB_WIZARD, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_TB_EXTRACTPROJECT, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_TB_BLOCKCOMMENT, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_TB_LINECOMMENT, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_TB_RUNHTML, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_TB_RUNCHM, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_TB_CONFIG, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_MENU_DOXYBLOCKS, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_MENU_EXTRACTPROJECT, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_MENU_BLOCKCOMMENT, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_MENU_LINECOMMENT, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_MENU_RUNHTML, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_MENU_RUNCHM, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_MENU_CONFIG, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_MENU_SAVE_TEMPLATE, DoxyBlocks::OnUpdateUI )
  EVT_UPDATE_UI( ID_MENU_LOAD_TEMPLATE, DoxyBlocks::OnUpdateUI )
  EVT_TEXT_URL( ID_LOG_DOXYBLOCKS, DoxyBlocks::OnTextURL )
END_EVENT_TABLE()

DoxyBlocks::DoxyBlocks() :
  m_pToolbar( 0l ),
  m_DoxyBlocksLog( 0l ),
  m_LogPageIndex( 0 ),
  m_bAutoVersioning( false ) {
  if( !Manager::LoadResource( wxT( "DoxyBlocks.zip" ) ) ) {
    NotifyMissingFile( wxT( "DoxyBlocks.zip" ) );
  }
  m_pConfig = new DoxyBlocksConfig;
}

DoxyBlocks::~DoxyBlocks() {
  wxDELETE( m_pConfig );
  wxASSERT( !m_pConfig );
}

void DoxyBlocks::OnAttach() {
  Manager::Get()->RegisterEventSink( cbEVT_PROJECT_ACTIVATE, new cbEventFunctor<DoxyBlocks, CodeBlocksEvent>( this, &DoxyBlocks::OnProjectActivate ) );
  Manager::Get()->RegisterEventSink( cbEVT_EDITOR_OPEN, new cbEventFunctor<DoxyBlocks, CodeBlocksEvent>( this, &DoxyBlocks::OnEditorOpen ) );
  Manager::Get()->RegisterEventSink( cbEVT_EDITOR_CLOSE, new cbEventFunctor<DoxyBlocks, CodeBlocksEvent>( this, &DoxyBlocks::OnEditorClose ) );
  if( LogManager *LogMan = Manager::Get()->GetLogManager() ) {
    m_DoxyBlocksLog = new DoxyBlocksLogger();
    m_LogPageIndex = LogMan->SetLog( m_DoxyBlocksLog );
    LogMan->Slot( m_LogPageIndex ).title = wxT( "DoxyBlocks" );
    CodeBlocksLogEvent evtAdd( cbEVT_ADD_LOG_WINDOW, m_DoxyBlocksLog, LogMan->Slot( m_LogPageIndex ).title );
    Manager::Get()->ProcessEvent( evtAdd );
  }
}

void DoxyBlocks::OnProjectActivate( CodeBlocksEvent& ( event ) ) {
  if( IsAttached() ) {
    if( m_pConfig != NULL ) {
      wxDELETE( m_pConfig );
      wxASSERT( !m_pConfig );
    }
    m_pConfig = new DoxyBlocksConfig;
    CheckForAutoVersioning();
    LoadSettings();
  }
  m_pToolbar->Enable( true );
  wxMenuBar *menuBar =  Manager::Get()->GetAppFrame()->GetMenuBar();
  menuBar->FindItem( ID_MENU_DOXYWIZARD )->Enable( true );
  menuBar->FindItem( ID_MENU_EXTRACTPROJECT )->Enable( true );
  menuBar->FindItem( ID_MENU_RUNHTML )->Enable( true );
  menuBar->FindItem( ID_MENU_RUNCHM )->Enable( true );
  menuBar->FindItem( ID_MENU_CONFIG )->Enable( true );
  menuBar->FindItem( ID_MENU_LOAD_TEMPLATE )->Enable( true );
  menuBar->FindItem( ID_MENU_SAVE_TEMPLATE )->Enable( true );
  if( Manager::Get()->GetEditorManager()->GetEditorsCount() > 0 ) {
    menuBar->FindItem( ID_MENU_BLOCKCOMMENT )->Enable( true );
    menuBar->FindItem( ID_MENU_LINECOMMENT )->Enable( true );
  } else {
    m_pToolbar->EnableTool( ID_TB_BLOCKCOMMENT, false );
    m_pToolbar->EnableTool( ID_TB_LINECOMMENT, false );
    menuBar->FindItem( ID_MENU_BLOCKCOMMENT )->Enable( false );
    menuBar->FindItem( ID_MENU_LINECOMMENT )->Enable( false );
  }
}

void DoxyBlocks::OnEditorOpen( CodeBlocksEvent& ( event ) ) {
  if( IsAttached() ) {
    if( Manager::Get()->GetEditorManager()->GetEditorsCount() == 1 ) {
      m_pToolbar->EnableTool( ID_TB_BLOCKCOMMENT, true );
      m_pToolbar->EnableTool( ID_TB_LINECOMMENT, true );
      wxMenuBar *menuBar =  Manager::Get()->GetAppFrame()->GetMenuBar();
      menuBar->FindItem( ID_MENU_BLOCKCOMMENT )->Enable( true );
      menuBar->FindItem( ID_MENU_LINECOMMENT )->Enable( true );
    }
  }
}

void DoxyBlocks::OnEditorClose( CodeBlocksEvent& ( event ) ) {
  if( IsAttached() ) {
    if( Manager::Get()->GetEditorManager()->GetEditorsCount() == 0 ) {
      m_pToolbar->EnableTool( ID_TB_BLOCKCOMMENT, false );
      m_pToolbar->EnableTool( ID_TB_LINECOMMENT, false );
      wxMenuBar *menuBar =  Manager::Get()->GetAppFrame()->GetMenuBar();
      menuBar->FindItem( ID_MENU_BLOCKCOMMENT )->Enable( false );
      menuBar->FindItem( ID_MENU_LINECOMMENT )->Enable( false );
    }
  }
}

void DoxyBlocks::OnUpdateUI( wxUpdateUIEvent& ( event ) ) {
  if( Manager::Get()->GetProjectManager()->GetProjects()->GetCount() == 0 ) {
    m_pToolbar->Enable( false );
    wxMenuBar *menuBar =  Manager::Get()->GetAppFrame()->GetMenuBar();
    menuBar->FindItem( ID_MENU_DOXYWIZARD )->Enable( false );
    menuBar->FindItem( ID_MENU_EXTRACTPROJECT )->Enable( false );
    menuBar->FindItem( ID_MENU_BLOCKCOMMENT )->Enable( false );
    menuBar->FindItem( ID_MENU_LINECOMMENT )->Enable( false );
    menuBar->FindItem( ID_MENU_RUNHTML )->Enable( false );
    menuBar->FindItem( ID_MENU_RUNCHM )->Enable( false );
    menuBar->FindItem( ID_MENU_CONFIG )->Enable( false );
    menuBar->FindItem( ID_MENU_LOAD_TEMPLATE )->Enable( false );
    menuBar->FindItem( ID_MENU_SAVE_TEMPLATE )->Enable( false );
  }
}

void DoxyBlocks::OnRelease( bool ) {
  if( Manager::Get()->GetLogManager() ) {
    if( m_DoxyBlocksLog ) {
      CodeBlocksLogEvent evt( cbEVT_REMOVE_LOG_WINDOW, m_DoxyBlocksLog );
      Manager::Get()->ProcessEvent( evt );
    }
  }
  m_DoxyBlocksLog = 0;
}

cbConfigurationPanel *DoxyBlocks::GetConfigurationPanel( wxWindow *parent ) {
  if( !IsAttached() ) {
    return 0;
  }
  if( m_bAutoVersioning ) {
    if( m_pConfig->GetUseAutoVersion() ) {
      m_sAutoVersion = GetAutoVersion();
      m_pConfig->SetProjectNumber( m_sAutoVersion );
    }
  }
  ConfigPanel *pDlg = new ConfigPanel( parent, this );
  pDlg->SetAutoVersioning( m_bAutoVersioning );
  pDlg->SetBlockComment( m_pConfig->GetBlockComment() );
  pDlg->SetLineComment( m_pConfig->GetLineComment() );
  pDlg->SetProjectNumber( m_pConfig->GetProjectNumber() );
  pDlg->SetOutputDirectory( m_pConfig->GetOutputDirectory() );
  pDlg->SetOutputLanguage( m_pConfig->GetOutputLanguage() );
  pDlg->SetUseAutoVersion( m_pConfig->GetUseAutoVersion() );
  pDlg->SetExtractAll( m_pConfig->GetExtractAll() );
  pDlg->SetExtractPrivate( m_pConfig->GetExtractPrivate() );
  pDlg->SetExtractStatic( m_pConfig->GetExtractStatic() );
  pDlg->SetWarnings( m_pConfig->GetWarnings() );
  pDlg->SetWarnIfDocError( m_pConfig->GetWarnIfDocError() );
  pDlg->SetWarnIfUndocumented( m_pConfig->GetWarnIfUndocumented() );
  pDlg->SetWarnNoParamdoc( m_pConfig->GetWarnNoParamdoc() );
  pDlg->SetAlphabeticalIndex( m_pConfig->GetAlphabeticalIndex() );
  pDlg->SetGenerateHTML( m_pConfig->GetGenerateHTML() );
  pDlg->SetGenerateHTMLHelp( m_pConfig->GetGenerateHTMLHelp() );
  pDlg->SetGenerateCHI( m_pConfig->GetGenerateCHI() );
  pDlg->SetBinaryTOC( m_pConfig->GetBinaryTOC() );
  pDlg->SetGenerateLatex( m_pConfig->GetGenerateLatex() );
  pDlg->SetGenerateRTF( m_pConfig->GetGenerateRTF() );
  pDlg->SetGenerateMan( m_pConfig->GetGenerateMan() );
  pDlg->SetGenerateXML( m_pConfig->GetGenerateXML() );
  pDlg->SetGenerateAutogenDef( m_pConfig->GetGenerateAutogenDef() );
  pDlg->SetGeneratePerlMod( m_pConfig->GetGeneratePerlMod() );
  pDlg->SetEnablePreprocessing( m_pConfig->GetEnablePreprocessing() );
  pDlg->SetClassDiagrams( m_pConfig->GetClassDiagrams() );
  pDlg->SetHaveDot( m_pConfig->GetHaveDot() );
  pDlg->SetPathDoxygen( m_pConfig->GetPathDoxygen() );
  pDlg->SetPathDoxywizard( m_pConfig->GetPathDoxywizard() );
  pDlg->SetPathHHC( m_pConfig->GetPathHHC() );
  pDlg->SetPathCHMViewer( m_pConfig->GetPathCHMViewer() );
  pDlg->SetPathDot( m_pConfig->GetPathDot() );
  pDlg->SetOverwriteDoxyfile( m_pConfig->GetOverwriteDoxyfile() );
  pDlg->SetPromptBeforeOverwriting( m_pConfig->GetPromptBeforeOverwriting() );
  pDlg->SetUseAtInTags( m_pConfig->GetUseAtInTags() );
  pDlg->SetLoadTemplate( m_pConfig->GetLoadTemplate() );
  pDlg->SetUseInternalViewer( m_pConfig->GetUseInternalViewer() );
  pDlg->SetRunHTML( m_pConfig->GetRunHTML() );
  pDlg->SetRunCHM( m_pConfig->GetRunCHM() );
  pDlg->Init();
  return pDlg;
}

cbConfigurationPanel* DoxyBlocks::GetProjectConfigurationPanel( wxWindow*, M_Code_Project* ) {
  return 0;
}

void DoxyBlocks::OnConfigure( wxCommandEvent & ( event ) ) {
  Configure();
}

int DoxyBlocks::Configure() {
  cbConfigurationDialog dlg( Manager::Get()->GetAppWindow(), wxID_ANY, _( "DoxyBlocks" ) );
  cbConfigurationPanel *panel = GetConfigurationPanel( &dlg );
  if( panel ) {
    dlg.AttachConfigurationPanel( panel );
    PlaceWindow( &dlg );
    return dlg.ShowModal() == wxID_OK ? 0 : -1;
  }
  return -1;
}

void DoxyBlocks::OnDialogueDone( ConfigPanel* pDlg ) {
  bool dirty = false;
  if( m_pConfig->GetBlockComment() != pDlg->GetBlockComment() ) {
    dirty = true;
  }
  m_pConfig->SetBlockComment( pDlg->GetBlockComment() );
  if( m_pConfig->GetLineComment() != pDlg->GetLineComment() ) {
    dirty = true;
  }
  m_pConfig->SetLineComment( pDlg->GetLineComment() );
  if( m_pConfig->GetProjectNumber() != pDlg->GetProjectNumber() ) {
    dirty = true;
  }
  m_pConfig->SetProjectNumber( pDlg->GetProjectNumber() );
  if( m_pConfig->GetOutputDirectory() != pDlg->GetOutputDirectory() ) {
    dirty = true;
  }
  m_pConfig->SetOutputDirectory( ValidateRelativePath( pDlg->GetOutputDirectory() ) );
  if( m_pConfig->GetOutputLanguage() != pDlg->GetOutputLanguage() ) {
    dirty = true;
  }
  m_pConfig->SetOutputLanguage( pDlg->GetOutputLanguage() );
  if( m_pConfig->GetUseAutoVersion() != pDlg->GetUseAutoVersion() ) {
    dirty = true;
  }
  m_pConfig->SetUseAutoVersion( pDlg->GetUseAutoVersion() );
  if( m_pConfig->GetExtractAll() != pDlg->GetExtractAll() ) {
    dirty = true;
  }
  m_pConfig->SetExtractAll( pDlg->GetExtractAll() );
  if( m_pConfig->GetExtractPrivate() != pDlg->GetExtractPrivate() ) {
    dirty = true;
  }
  m_pConfig->SetExtractPrivate( pDlg->GetExtractPrivate() );
  if( m_pConfig->GetExtractStatic() != pDlg->GetExtractStatic() ) {
    dirty = true;
  }
  m_pConfig->SetExtractStatic( pDlg->GetExtractStatic() );
  if( m_pConfig->GetWarnings() != pDlg->GetWarnings() ) {
    dirty = true;
  }
  m_pConfig->SetWarnings( pDlg->GetWarnings() );
  if( m_pConfig->GetWarnIfDocError() != pDlg->GetWarnIfDocError() ) {
    dirty = true;
  }
  m_pConfig->SetWarnIfDocError( pDlg->GetWarnIfDocError() );
  if( m_pConfig->GetWarnIfUndocumented() != pDlg->GetWarnIfUndocumented() ) {
    dirty = true;
  }
  m_pConfig->SetWarnIfUndocumented( pDlg->GetWarnIfUndocumented() );
  if( m_pConfig->GetWarnNoParamdoc() != pDlg->GetWarnNoParamdoc() ) {
    dirty = true;
  }
  m_pConfig->SetWarnNoParamdoc( pDlg->GetWarnNoParamdoc() );
  if( m_pConfig->GetAlphabeticalIndex() != pDlg->GetAlphabeticalIndex() ) {
    dirty = true;
  }
  m_pConfig->SetAlphabeticalIndex( pDlg->GetAlphabeticalIndex() );
  if( m_pConfig->GetGenerateHTML() != pDlg->GetGenerateHTML() ) {
    dirty = true;
  }
  m_pConfig->SetGenerateHTML( pDlg->GetGenerateHTML() );
  if( m_pConfig->GetGenerateHTMLHelp() != pDlg->GetGenerateHTMLHelp() ) {
    dirty = true;
  }
  m_pConfig->SetGenerateHTMLHelp( pDlg->GetGenerateHTMLHelp() );
  if( m_pConfig->GetGenerateCHI() != pDlg->GetGenerateCHI() ) {
    dirty = true;
  }
  m_pConfig->SetGenerateCHI( pDlg->GetGenerateCHI() );
  if( m_pConfig->GetBinaryTOC() != pDlg->GetBinaryTOC() ) {
    dirty = true;
  }
  m_pConfig->SetBinaryTOC( pDlg->GetBinaryTOC() );
  if( m_pConfig->GetGenerateLatex() != pDlg->GetGenerateLatex() ) {
    dirty = true;
  }
  m_pConfig->SetGenerateLatex( pDlg->GetGenerateLatex() );
  if( m_pConfig->GetGenerateRTF() != pDlg->GetGenerateRTF() ) {
    dirty = true;
  }
  m_pConfig->SetGenerateRTF( pDlg->GetGenerateRTF() );
  if( m_pConfig->GetGenerateMan() != pDlg->GetGenerateMan() ) {
    dirty = true;
  }
  m_pConfig->SetGenerateMan( pDlg->GetGenerateMan() );
  if( m_pConfig->GetGenerateXML() != pDlg->GetGenerateXML() ) {
    dirty = true;
  }
  m_pConfig->SetGenerateXML( pDlg->GetGenerateXML() );
  if( m_pConfig->GetGenerateAutogenDef() != pDlg->GetGenerateAutogenDef() ) {
    dirty = true;
  }
  m_pConfig->SetGenerateAutogenDef( pDlg->GetGenerateAutogenDef() );
  if( m_pConfig->GetGeneratePerlMod() != pDlg->GetGeneratePerlMod() ) {
    dirty = true;
  }
  m_pConfig->SetGeneratePerlMod( pDlg->GetGeneratePerlMod() );
  if( m_pConfig->GetEnablePreprocessing() != pDlg->GetEnablePreprocessing() ) {
    dirty = true;
  }
  m_pConfig->SetEnablePreprocessing( pDlg->GetEnablePreprocessing() );
  if( m_pConfig->GetClassDiagrams() != pDlg->GetClassDiagrams() ) {
    dirty = true;
  }
  m_pConfig->SetClassDiagrams( pDlg->GetClassDiagrams() );
  if( m_pConfig->GetHaveDot() != pDlg->GetHaveDot() ) {
    dirty = true;
  }
  m_pConfig->SetHaveDot( pDlg->GetHaveDot() );
  if( m_pConfig->GetPathDoxygen() != pDlg->GetPathDoxygen() ) {
    dirty = true;
  }
  m_pConfig->SetPathDoxygen( pDlg->GetPathDoxygen() );
  if( m_pConfig->GetPathDoxywizard() != pDlg->GetPathDoxywizard() ) {
    dirty = true;
  }
  m_pConfig->SetPathDoxywizard( pDlg->GetPathDoxywizard() );
  if( m_pConfig->GetPathHHC() != pDlg->GetPathHHC() ) {
    dirty = true;
  }
  m_pConfig->SetPathHHC( pDlg->GetPathHHC() );
  if( m_pConfig->GetPathDot() != pDlg->GetPathDot() ) {
    dirty = true;
  }
  m_pConfig->SetPathDot( pDlg->GetPathDot() );
  if( m_pConfig->GetPathCHMViewer() != pDlg->GetPathCHMViewer() ) {
    dirty = true;
  }
  m_pConfig->SetPathCHMViewer( pDlg->GetPathCHMViewer() );
  if( m_pConfig->GetOverwriteDoxyfile() != pDlg->GetOverwriteDoxyfile() ) {
    dirty = true;
  }
  m_pConfig->SetOverwriteDoxyfile( pDlg->GetOverwriteDoxyfile() );
  if( m_pConfig->GetPromptBeforeOverwriting() != pDlg->GetPromptBeforeOverwriting() ) {
    dirty = true;
  }
  m_pConfig->SetPromptBeforeOverwriting( pDlg->GetPromptBeforeOverwriting() );
  if( m_pConfig->GetUseAtInTags() != pDlg->GetUseAtInTags() ) {
    dirty = true;
  }
  m_pConfig->SetUseAtInTags( pDlg->GetUseAtInTags() );
  if( m_pConfig->GetLoadTemplate() != pDlg->GetLoadTemplate() ) {
    dirty = true;
  }
  m_pConfig->SetLoadTemplate( pDlg->GetLoadTemplate() );
  if( m_pConfig->GetUseInternalViewer() != pDlg->GetUseInternalViewer() ) {
    dirty = true;
  }
  m_pConfig->SetUseInternalViewer( pDlg->GetUseInternalViewer() );
  if( m_pConfig->GetRunHTML() != pDlg->GetRunHTML() ) {
    dirty = true;
  }
  m_pConfig->SetRunHTML( pDlg->GetRunHTML() );
  if( m_pConfig->GetRunCHM() != pDlg->GetRunCHM() ) {
    dirty = true;
  }
  m_pConfig->SetRunCHM( pDlg->GetRunCHM() );
  if( dirty ) {
    M_Code_Project *prj = Manager::Get()->GetProjectManager()->GetActiveProject();
    if( prj ) {
      SaveSettings();
      prj->Save();
    } else {
      AppendToLog( _( "No active project found. Settings not saved." ), LOG_WARNING );
    }
  }
}

// TODO (m#1#2019年07月27日): 增加菜单

void DoxyBlocks::BuildMenu( wxMenuBar *menuBar ) {
  int idx = menuBar->FindMenu( _( "P&lugins" ) );
  if( idx != wxNOT_FOUND ) {
    wxMenu *submenu = new wxMenu;
    wxString sDataFolder( ConfigManager::GetDataFolder() );
    wxString prefix = sDataFolder + wxT( "/images/DoxyBlocks/16x16/" );
    wxMenuItem *MenuItemDoxywizard = new wxMenuItem( submenu, ID_MENU_DOXYWIZARD, _( "&Doxywizard...\tCtrl-Shift-D" ), _( "Run doxywizard." ) );
    MenuItemDoxywizard->SetBitmap( wxBitmap( prefix + wxT( "doxywizard.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemDoxywizard );
    wxMenuItem *MenuItemExtract = new wxMenuItem( submenu, ID_MENU_EXTRACTPROJECT, _( "&Extract documentation" ), _( "Extract documentation for the current project." ) );
    MenuItemExtract->SetBitmap( wxBitmap( prefix + wxT( "extract.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemExtract );
    wxMenuItem *MenuItemBlockComment = new wxMenuItem( submenu, ID_MENU_BLOCKCOMMENT, _( "&Block comment" ), _( "Insert a comment block at the current line." ) );
    MenuItemBlockComment->SetBitmap( wxBitmap( prefix + wxT( "comment_block.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemBlockComment );
    wxMenuItem *MenuItemLineComment = new wxMenuItem( submenu, ID_MENU_LINECOMMENT, _( "&Line comment" ), _( "Insert a line comment at the current cursor position." ) );
    MenuItemLineComment->SetBitmap( wxBitmap( prefix + wxT( "comment_line.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemLineComment );
    wxMenuItem *MenuItemRunHTML = new wxMenuItem( submenu, ID_MENU_RUNHTML, _( "Run &HTML\tCtrl-Shift-H" ), _( "Run HTML documentation." ) );
    MenuItemRunHTML->SetBitmap( wxBitmap( prefix + wxT( "html.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemRunHTML );
    wxMenuItem *MenuItemRunCHM = new wxMenuItem( submenu, ID_MENU_RUNCHM, _( "Run &CHM" ), _( "Run CHM documentation." ) );
    MenuItemRunCHM->SetBitmap( wxBitmap( prefix + wxT( "chm.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemRunCHM );
    wxMenuItem *MenuItemConfig = new wxMenuItem( submenu, ID_MENU_CONFIG, _( "Open &preferences..." ), _( "Open DoxyBlocks' preferences." ) );
    MenuItemConfig->SetBitmap( wxBitmap( prefix + wxT( "configure.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemConfig );
    wxMenuItem *MenuItemLoadTemplate = new wxMenuItem( submenu, ID_MENU_LOAD_TEMPLATE, _( "L&oad settings template" ), _( "Load saved settings template." ) );
    MenuItemLoadTemplate->SetBitmap( wxBitmap( sDataFolder + wxT( "/images/16x16/fileopen.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemLoadTemplate );
    wxMenuItem *MenuItemSaveTemplate = new wxMenuItem( submenu, ID_MENU_SAVE_TEMPLATE, _( "&Save settings template" ), _( "Save current settings for future use." ) );
    MenuItemSaveTemplate->SetBitmap( wxBitmap( sDataFolder + wxT( "/images/16x16/filesave.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemSaveTemplate );
    Connect( ID_MENU_DOXYWIZARD,     wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnRunDoxywizard ) );
    Connect( ID_MENU_EXTRACTPROJECT, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnExtractProject ) );
    Connect( ID_MENU_BLOCKCOMMENT,   wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnBlockComment ) );
    Connect( ID_MENU_LINECOMMENT,    wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnLineComment ) );
    Connect( ID_MENU_RUNHTML,        wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnRunHTML ) );
    Connect( ID_MENU_RUNCHM,         wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnRunCHM ) );
    Connect( ID_MENU_CONFIG,         wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnConfigure ) );
    Connect( ID_MENU_LOAD_TEMPLATE,  wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnReadPrefsTemplate ) );
    Connect( ID_MENU_SAVE_TEMPLATE,  wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnWritePrefsTemplate ) );
    menuBar->Insert( idx + 1, submenu, wxT( "Do&xyBlocks" ) );
  }
}

void DoxyBlocks::BuildModuleMenu( const ModuleType type, wxMenu *menu, const FileTreeData * ) {
  if( type == mtEditorManager ) {
    wxMenu *submenu = new wxMenu;
    wxString prefix = ConfigManager::GetDataFolder() + wxT( "/images/DoxyBlocks/16x16/" );
    wxMenuItem *MenuItemBlockComment = new wxMenuItem( submenu, ID_MENU_BLOCKCOMMENT, _( "&Block Comment" ), _( "Insert a comment block at the current line." ) );
    MenuItemBlockComment->SetBitmap( wxBitmap( prefix + wxT( "comment_block.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemBlockComment );
    wxMenuItem *MenuItemLineComment = new wxMenuItem( submenu, ID_MENU_LINECOMMENT, _( "&Line Comment" ), _( "Insert a line comment at the current cursor position." ) );
    MenuItemLineComment->SetBitmap( wxBitmap( prefix + wxT( "comment_line.png" ), wxBITMAP_TYPE_PNG ) );
    submenu->Append( MenuItemLineComment );
    menu->AppendSubMenu( submenu, wxT( "Do&xyBlocks" ) );
  }
}

bool DoxyBlocks::BuildToolBar( wxToolBar *toolBar ) {
  if( !IsAttached() || !toolBar ) {
    return false;
  }
  m_pToolbar = toolBar;
  wxString prefix;
  ConfigManager *cfg = Manager::Get()->GetConfigManager( wxT( "app" ) );
  if( cfg->ReadBool( wxT( "/environment/toolbar_size" ), true ) ) {
    prefix = ConfigManager::GetDataFolder() + wxT( "/images/DoxyBlocks/16x16/" );
    m_pToolbar->SetToolBitmapSize( wxSize( 16, 16 ) );
  } else {
    prefix = ConfigManager::GetDataFolder() + wxT( "/images/DoxyBlocks/" );
    m_pToolbar->SetToolBitmapSize( wxSize( 22, 22 ) );
  }
  m_pToolbar->AddTool( ID_TB_WIZARD, _( "Doxywizard" ), wxBitmap( prefix + wxT( "doxywizard.png" ), wxBITMAP_TYPE_PNG ), wxNullBitmap, wxITEM_NORMAL, _( "Run doxywizard" ) );
  m_pToolbar->AddTool( ID_TB_EXTRACTPROJECT, _( "Document project" ), wxBitmap( prefix + wxT( "extract.png" ), wxBITMAP_TYPE_PNG ), wxNullBitmap, wxITEM_NORMAL, _( "Extract documentation for the current project" ) );
  m_pToolbar->AddSeparator();
  m_pToolbar->AddTool( ID_TB_BLOCKCOMMENT, _( "Block Comment" ), wxBitmap( prefix + wxT( "comment_block.png" ), wxBITMAP_TYPE_PNG ), wxNullBitmap, wxITEM_NORMAL, _( "Insert a comment block at the current line" ) );
  m_pToolbar->AddTool( ID_TB_LINECOMMENT, _( "Line Comment" ), wxBitmap( prefix + wxT( "comment_line.png" ), wxBITMAP_TYPE_PNG ), wxNullBitmap, wxITEM_NORMAL, _( "Insert a line comment at the current cursor position" ) );
  m_pToolbar->AddSeparator();
  m_pToolbar->AddTool( ID_TB_RUNHTML, _( "Run HTML" ), wxBitmap( prefix + wxT( "html.png" ), wxBITMAP_TYPE_PNG ), wxNullBitmap, wxITEM_NORMAL, _( "Run HTML documentation" ) );
  m_pToolbar->AddTool( ID_TB_RUNCHM, _( "Run CHM" ), wxBitmap( prefix + wxT( "chm.png" ), wxBITMAP_TYPE_PNG ), wxNullBitmap, wxITEM_NORMAL, _( "Run HTML Help documentation" ) );
  m_pToolbar->AddSeparator();
  m_pToolbar->AddTool( ID_TB_CONFIG, _( "Open Preferences" ), wxBitmap( prefix + wxT( "configure.png" ), wxBITMAP_TYPE_PNG ), wxNullBitmap, wxITEM_NORMAL, _( "Open DoxyBlocks' preferences" ) );
  m_pToolbar->Realize();
  m_pToolbar->SetInitialSize();
  Connect( ID_TB_WIZARD,         wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnRunDoxywizard ) );
  Connect( ID_TB_EXTRACTPROJECT, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnExtractProject ) );
  Connect( ID_TB_BLOCKCOMMENT,   wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnBlockComment ) );
  Connect( ID_TB_LINECOMMENT,    wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnLineComment ) );
  Connect( ID_TB_RUNHTML,        wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnRunHTML ) );
  Connect( ID_TB_RUNCHM,         wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnRunCHM ) );
  Connect( ID_TB_CONFIG,         wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( DoxyBlocks::OnConfigure ) );
  return true;
}


void DoxyBlocks::OnRunDoxywizard( wxCommandEvent & ( event ) ) {
  DoRunDoxywizard();
}


bool DoxyBlocks::DoRunDoxywizard() {
  if( !IsProjectOpen() ) {
    return false;
  }
  AppendToLog( _( "Running doxywizard..." ) );
  wxString cmd = wxT( "doxywizard" );
  wxString sDoxywizardPath = Manager::Get()->GetMacrosManager()->ReplaceMacros( m_pConfig->GetPathDoxywizard() );
  if( !sDoxywizardPath.IsEmpty() ) {
    cmd = sDoxywizardPath;
  }
  wxString sPathDoxyfile = wxT( "doxygen" );
  wxString sOutputDir =  m_pConfig->GetOutputDirectory();
  if( !sOutputDir.IsEmpty() ) {
    sPathDoxyfile = sPathDoxyfile + wxT( "/" ) + sOutputDir;
  }
  wxString sCfgBaseFile = wxT( "doxyfile" );
  wxFileName fnDoxyfile( sPathDoxyfile + wxFileName::GetPathSeparator() + sCfgBaseFile );
  fnDoxyfile.Normalize();
  if( !sPathDoxyfile.IsEmpty() ) {
    wxString fullpath = fnDoxyfile.GetFullPath();
    QuoteStringIfNeeded( fullpath );
    cmd.Append( wxT( " " ) + fullpath );
  }
  wxProcess *process = new wxProcess( this );
  long pid = wxExecute( cmd, wxEXEC_ASYNC, process );
  if( !pid ) {
    AppendToLog( wxString::Format( _( "Execution of '%s' failed." ), cmd.c_str() ), LOG_ERROR );
    AppendToLog( _( "Please ensure that the doxygen 'bin' directory is in your path or provide the specific path in DoxyBlocks' preferences.\n" ) );
    delete process;
  } else {
    AppendToLog( wxString::Format( _( "Process %ld (%s) launched." ), pid, cmd.c_str() ) );
  }
  return true;
}


void DoxyBlocks::AppendToLog( const wxString &sText, eLogLevel flag, bool bReturnFocus ) const {
  if( LogManager *LogMan = Manager::Get()->GetLogManager() ) {
    CodeBlocksLogEvent evtSwitch( cbEVT_SWITCH_TO_LOG_WINDOW, m_DoxyBlocksLog );
    Manager::Get()->ProcessEvent( evtSwitch );
    switch( flag ) {
      case LOG_NORMAL:
        LogMan->Log( sText, m_LogPageIndex );
        break;
      case LOG_WARNING:
        LogMan->LogWarning( sText, m_LogPageIndex );
        break;
      case LOG_ERROR:
        LogMan->LogError( sText, m_LogPageIndex );
        break;
      default:
        break;
    }
    if( bReturnFocus ) {
      M_Code_Editor *cbEd = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
      if( cbEd ) {
        cbEd->GetControl()->SetFocus();
      }
    }
  }
}


bool DoxyBlocks::IsProjectOpen() const {
  const M_Code_Project* project = Manager::Get()->GetProjectManager()->GetActiveProject();
  if( !project ) {
    const wxString msg = _( "使用前需要打开项目 DoxyBlocks." );
    msging( msg, wxString( wxT( "DoxyBlocks " ) ) + _( "错误" ), wxICON_ERROR | wxOK, Manager::Get()->GetAppWindow() );
    AppendToLog( msg, LOG_ERROR, false );
    return false;
  }
  return true;
}

void DoxyBlocks::OnRunHTML( wxCommandEvent & ( event ) ) {
  DoRunHTML();
}


void DoxyBlocks::DoRunHTML() {
  if( !IsProjectOpen() ) {
    return;
  }
  wxString sDocPath = GetDocPath();
  if( sDocPath.IsEmpty() ) {
    AppendToLog( _( "Unable to get the doxygen document path." ), LOG_ERROR );
    return;
  }
  wxString sPath( sDocPath + wxT( "html/index.html" ) );
  wxString sURL = wxT( "file://" ) + sPath;
  bool bUseInternalViewer = m_pConfig->GetUseInternalViewer();
  if( wxFile::Exists( sPath ) ) {
    if( bUseInternalViewer ) {
      if( cbMimePlugin* p = Manager::Get()->GetPluginManager()->GetMIMEHandlerForFile( sPath ) ) {
        p->OpenFile( sPath );
        AppendToLog( _( "Internal viewer launched with path " ) + sPath + wxT( "." ) );
      } else {
        AppendToLog( _( "Error getting MIME handler for " ) + sPath, LOG_ERROR );
      }
    } else {
      if( !wxLaunchDefaultBrowser( sURL ) ) {
        AppendToLog( _( "Unable to launch the default browser." ), LOG_WARNING );
      } else {
        AppendToLog( _( "Default browser launched with URL " ) + sURL + wxT( "." ) );
      }
    }
  } else {
    AppendToLog( _( "Index.html not found at " ) + sPath + wxT( "." ), LOG_WARNING );
  }
}

void DoxyBlocks::OnRunCHM( wxCommandEvent & ( event ) ) {
  DoRunCHM();
}


void DoxyBlocks::DoRunCHM() {
  if( !IsProjectOpen() ) {
    return;
  }
  const wxString sPrjName = GetProjectName();
  const wxString sDocPath = GetDocPath();
  if( sPrjName.IsEmpty() ) {
    AppendToLog( _( "Unable to get the project name." ), LOG_ERROR );
    return;
  }
  if( sDocPath.IsEmpty() ) {
    AppendToLog( _( "Unable to get the doxygen document path." ), LOG_ERROR );
    return;
  }
  RunCompiledHelp( sDocPath, sPrjName );
}


void DoxyBlocks::RunCompiledHelp( wxString sDocPath, wxString sPrjName ) {
  wxString sPathCHM = sDocPath + sPrjName + wxT( ".chm" );
  if( wxFile::Exists( sPathCHM ) ) {
    wxString cmdCHM;
    wxString sCHMViewer = Manager::Get()->GetMacrosManager()->ReplaceMacros( m_pConfig->GetPathCHMViewer() );
    if( sCHMViewer.IsEmpty() ) {
      if( ( wxPlatformInfo::Get().GetOperatingSystemId() & wxOS_WINDOWS ) > 0 ) {
        cmdCHM = wxT( "CMD /C " ) + sPathCHM;
      } else {
        cmdCHM = sPathCHM;
      }
    } else {
      cmdCHM = sCHMViewer + wxT( " " ) + sPathCHM;
    }
    wxProcess *proc = wxProcess::Open( cmdCHM );
    if( proc == NULL ) {
      AppendToLog( wxString::Format( _( "Execution of '%s' failed." ), cmdCHM.c_str() ), LOG_ERROR );
    } else {
      AppendToLog( wxString::Format( _( "Process %ld (%s) launched." ), proc->GetPid(), cmdCHM.c_str() ) );
    }
  } else {
    AppendToLog( _( "HTML Help not found at " ) + sPathCHM + wxT( "." ), LOG_WARNING );
  }
}


wxString DoxyBlocks::GetProjectName() {
  return Manager::Get()->GetProjectManager()->GetActiveProject()->GetTitle();
}


wxString DoxyBlocks::GetDocPath() const {
  if( !IsProjectOpen() ) {
    return wxEmptyString;
  }
  const M_Code_Project* prj = Manager::Get()->GetProjectManager()->GetActiveProject();
  if( !prj ) {
    wxString sMsg = _( "Failed to get the active project!" );
    AppendToLog( sMsg, LOG_ERROR );
    return wxEmptyString;
  }
  wxString sDoxygenDir = prj->GetBasePath();
  const wxString sOutputDir = m_pConfig->GetOutputDirectory();
  if( !sOutputDir.IsEmpty() ) {
    sDoxygenDir = sDoxygenDir + sOutputDir;
  } else {
    sDoxygenDir = sDoxygenDir + wxT( "doxygen" );
  }
  sDoxygenDir = sDoxygenDir + wxFileName::GetPathSeparator();
  wxFileName fnDoxygenDir( sDoxygenDir );
  fnDoxygenDir.Normalize();
  return fnDoxygenDir.GetPathWithSep();
}


void DoxyBlocks::CheckForAutoVersioning() {
  m_bAutoVersioning = false;
  m_sAutoVersion = wxEmptyString;
  m_sVersionHeader = wxEmptyString;
  M_Code_Project* project = Manager::Get()->GetProjectManager()->GetActiveProject();
  TiXmlNode *node, *child;
  if( project ) {
    node = project->GetExtensionsNode();
    child = 0;
    while( ( child = node->IterateChildren( child ) ) ) {
      wxString sNodeValue = wxString( child->Value(), wxConvUTF8 );
      if( sNodeValue.Cmp( wxT( "AutoVersioning" ) ) == 0 ) {
        m_bAutoVersioning = true;
        TiXmlHandle Handle( child );
        if( const TiXmlElement* pElem = Handle.FirstChildElement( "Settings" ).ToElement() ) {
          m_sVersionHeader = wxString( pElem->Attribute( "header_path" ), wxConvUTF8 );
        } else {
          AppendToLog( _( "Unable to get the AutoVersion header path." ), LOG_ERROR );
        }
        break;
      }
    }
  }
}


wxString DoxyBlocks::GetAutoVersion() {
  wxString sAutoVersion( wxEmptyString );
  wxFileName fnVersionH( Manager::Get()->GetProjectManager()->GetActiveProject()->GetCommonTopLevelPath() + m_sVersionHeader );
  wxString sPathVersionH( fnVersionH.GetFullPath() );
  if( wxFile::Exists( sPathVersionH ) ) {
    wxTextFile fileVersionH( sPathVersionH );
    fileVersionH.Open();
    if( fileVersionH.IsOpened() ) {
      fileVersionH.GetFirstLine();
      wxString sLine;
      while( !fileVersionH.Eof() ) {
        sLine = fileVersionH.GetNextLine();
        if( sLine.Find( wxT( "FULLVERSION_STRING" ) ) != wxNOT_FOUND ) {
          sLine = sLine.AfterFirst( '"' );
          sAutoVersion = sLine.BeforeLast( '.' );
          break;
        }
      }
    } else {
      AppendToLog( _( "Unable to open the version header." ), LOG_ERROR );
    }
  } else {
    AppendToLog( _( "Version header " ) + sPathVersionH + _( " not found." ), LOG_ERROR );
  }
  return sAutoVersion;
}

void DoxyBlocks::LoadSettings() {
  ConfigManager* cfg = Manager::Get()->GetConfigManager( wxT( "editor" ) );
  int val = 0;
  M_Code_Project* prj = Manager::Get()->GetProjectManager()->GetActiveProject();
  if( prj ) {
    TiXmlElement *elem = prj->GetExtensionsNode()->ToElement();
    const TiXmlElement* node = elem->FirstChildElement( "DoxyBlocks" );
    if( node ) {
      TiXmlHandle handle( const_cast<TiXmlElement*>( node ) );
      if( const TiXmlElement* pElem = handle.FirstChildElement( "comment_style" ).ToElement() ) {
        if( pElem->QueryIntAttribute( "block", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetBlockComment( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "line", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetLineComment( static_cast<long>( val ) );
        }
      }
      if( const TiXmlElement* pElem = handle.FirstChildElement( "doxyfile_project" ).ToElement() ) {
        wxString s = wxString( pElem->Attribute( "project_number", &val ), wxConvUTF8 );
        if( !s.IsEmpty() ) {
          m_pConfig->SetProjectNumber( s );
        }
        s = wxString( pElem->Attribute( "output_directory", &val ), wxConvUTF8 );
        if( !s.IsEmpty() ) {
          m_pConfig->SetOutputDirectory( s );
        }
        s = wxString( pElem->Attribute( "output_language", &val ), wxConvUTF8 );
        if( !s.IsEmpty() ) {
          m_pConfig->SetOutputLanguage( s );
        }
        if( pElem->QueryIntAttribute( "use_auto_version", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetUseAutoVersion( static_cast<long>( val ) );
        }
      }
      if( const TiXmlElement* pElem = handle.FirstChildElement( "doxyfile_build" ).ToElement() ) {
        if( pElem->QueryIntAttribute( "extract_all", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetExtractAll( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "extract_private", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetExtractPrivate( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "extract_static", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetExtractStatic( static_cast<long>( val ) );
        }
      }
      if( const TiXmlElement* pElem = handle.FirstChildElement( "doxyfile_warnings" ).ToElement() ) {
        if( pElem->QueryIntAttribute( "warnings", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetWarnings( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "warn_if_doc_error", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetWarnIfDocError( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "warn_if_undocumented", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetWarnIfUndocumented( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "warn_no_param_doc", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetWarnNoParamdoc( static_cast<long>( val ) );
        }
      }
      if( const TiXmlElement* pElem = handle.FirstChildElement( "doxyfile_alpha_index" ).ToElement() ) {
        if( pElem->QueryIntAttribute( "alphabetical_index", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetAlphabeticalIndex( static_cast<long>( val ) );
        }
      }
      if( const TiXmlElement* pElem = handle.FirstChildElement( "doxyfile_output" ).ToElement() ) {
        if( pElem->QueryIntAttribute( "html", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetGenerateHTML( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "html_help", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetGenerateHTMLHelp( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "chi", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetGenerateCHI( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "binary_toc", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetBinaryTOC( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "latex", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetGenerateLatex( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "rtf", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetGenerateRTF( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "man", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetGenerateMan( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "xml", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetGenerateXML( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "autogen_def", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetGenerateAutogenDef( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "perl_mod", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetGeneratePerlMod( static_cast<long>( val ) );
        }
      }
      if( const TiXmlElement* pElem = handle.FirstChildElement( "doxyfile_preprocessor" ).ToElement() ) {
        if( pElem->QueryIntAttribute( "enable_preprocessing", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetEnablePreprocessing( static_cast<long>( val ) );
        }
      }
      if( const TiXmlElement* pElem = handle.FirstChildElement( "doxyfile_dot" ).ToElement() ) {
        if( pElem->QueryIntAttribute( "class_diagrams", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetClassDiagrams( static_cast<long>( val ) );
        }
        if( pElem->QueryIntAttribute( "have_dot", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetHaveDot( static_cast<long>( val ) );
        }
      }
      if( const TiXmlElement* pElem = handle.FirstChildElement( "general" ).ToElement() ) {
        if( pElem->QueryIntAttribute( "use_at_in_tags", &val ) == TIXML_SUCCESS ) {
          m_pConfig->SetUseAtInTags( static_cast<long>( val ) );
        }
      }
    } else {
      if( cfg->ReadBool( wxT( "doxyblocks/load_template" ) ) ) {
        DoReadPrefsTemplate();
      }
    }
  }
  m_pConfig->SetPathDoxygen( cfg->Read( wxT( "doxyblocks/path_doxygen" ) ) );
  m_pConfig->SetPathDoxywizard( cfg->Read( wxT( "doxyblocks/path_doxywizard" ) ) );
  m_pConfig->SetPathHHC( cfg->Read( wxT( "doxyblocks/path_hhc" ) ) );
  m_pConfig->SetPathDot( cfg->Read( wxT( "doxyblocks/path_dot" ) ) );
  m_pConfig->SetPathCHMViewer( cfg->Read( wxT( "doxyblocks/path_chm_viewer" ) ) );
  m_pConfig->SetOverwriteDoxyfile( cfg->ReadBool( wxT( "doxyblocks/overwrite_doxyfile" ), false ) );
  m_pConfig->SetPromptBeforeOverwriting( cfg->ReadBool( wxT( "doxyblocks/prompt_before_overwriting" ), false ) );
  m_pConfig->SetLoadTemplate( cfg->ReadBool( wxT( "doxyblocks/load_template" ), false ) );
  m_pConfig->SetUseInternalViewer( cfg->ReadBool( wxT( "doxyblocks/use_internal_viewer" ), false ) );
  m_pConfig->SetRunHTML( cfg->ReadBool( wxT( "doxyblocks/run_html" ), false ) );
  m_pConfig->SetRunCHM( cfg->ReadBool( wxT( "doxyblocks/run_chm" ), false ) );
}


void DoxyBlocks::SaveSettings() {
  wxString s;
  bool bVal;
  ConfigManager* cfg = Manager::Get()->GetConfigManager( wxT( "editor" ) );
  M_Code_Project* prj = Manager::Get()->GetProjectManager()->GetActiveProject();
  TiXmlElement *elem = prj->GetExtensionsNode()->ToElement();
  TiXmlElement* node = elem->FirstChildElement( "DoxyBlocks" );
  if( !node ) {
    node = elem->InsertEndChild( TiXmlElement( "DoxyBlocks" ) )->ToElement();
  }
  node->Clear();
  TiXmlElement Comment( "comment_style" );
  Comment.SetAttribute( "block", m_pConfig->GetBlockComment() );
  Comment.SetAttribute( "line", m_pConfig->GetLineComment() );
  node->InsertEndChild( Comment );
  TiXmlElement DoxyfileProject( "doxyfile_project" );
  s = m_pConfig->GetProjectNumber();
  if( !s.IsEmpty() ) {
    DoxyfileProject.SetAttribute( "project_number", s.mb_str() );
  }
  s = m_pConfig->GetOutputDirectory();
  if( !s.IsEmpty() ) {
    DoxyfileProject.SetAttribute( "output_directory", s.mb_str() );
  }
  s = m_pConfig->GetOutputLanguage();
  if( !s.IsSameAs( wxT( "English" ) ) ) {
    DoxyfileProject.SetAttribute( "output_language", s.mb_str() );
  }
  bVal = m_pConfig->GetUseAutoVersion();
  if( bVal ) {
    DoxyfileProject.SetAttribute( "use_auto_version", bVal );
  }
  node->InsertEndChild( DoxyfileProject );
  TiXmlElement DoxyfileBuild( "doxyfile_build" );
  bVal = m_pConfig->GetExtractAll();
  if( bVal ) {
    DoxyfileBuild.SetAttribute( "extract_all", bVal );
  }
  bVal = m_pConfig->GetExtractPrivate();
  if( bVal ) {
    DoxyfileBuild.SetAttribute( "extract_private", bVal );
  }
  bVal = m_pConfig->GetExtractStatic();
  if( bVal ) {
    DoxyfileBuild.SetAttribute( "extract_static", bVal );
  }
  node->InsertEndChild( DoxyfileBuild );
  TiXmlElement DoxyfileWarnings( "doxyfile_warnings" );
  bVal = m_pConfig->GetWarnings();
  if( !bVal ) {
    DoxyfileWarnings.SetAttribute( "warnings", bVal );
    bVal = m_pConfig->GetWarnIfDocError();
  }
  if( !bVal ) {
    DoxyfileWarnings.SetAttribute( "warn_if_doc_error", bVal );
  }
  bVal = m_pConfig->GetWarnIfUndocumented();
  if( bVal ) {
    DoxyfileWarnings.SetAttribute( "warn_if_undocumented", bVal );
  }
  bVal = m_pConfig->GetWarnNoParamdoc();
  if( !bVal ) {
    DoxyfileWarnings.SetAttribute( "warn_no_param_doc", bVal );
  }
  node->InsertEndChild( DoxyfileWarnings );
  bVal = m_pConfig->GetAlphabeticalIndex();
  if( !bVal ) {
    TiXmlElement DoxyfileAlphaIndex( "doxyfile_alpha_index" );
    DoxyfileAlphaIndex.SetAttribute( "alphabetical_index", bVal );
    node->InsertEndChild( DoxyfileAlphaIndex );
  }
  TiXmlElement DoxyfileOutput( "doxyfile_output" );
  bVal = m_pConfig->GetGenerateHTML();
  if( !bVal ) {
    DoxyfileOutput.SetAttribute( "html", bVal );
  }
  bVal = m_pConfig->GetGenerateHTMLHelp();
  if( bVal ) {
    DoxyfileOutput.SetAttribute( "html_help", bVal );
  }
  bVal = m_pConfig->GetGenerateCHI();
  if( bVal ) {
    DoxyfileOutput.SetAttribute( "chi", bVal );
  }
  bVal = m_pConfig->GetBinaryTOC();
  if( bVal ) {
    DoxyfileOutput.SetAttribute( "binary_toc", bVal );
  }
  bVal = m_pConfig->GetGenerateLatex();
  if( bVal ) {
    DoxyfileOutput.SetAttribute( "latex", bVal );
  }
  bVal = m_pConfig->GetGenerateRTF();
  if( bVal ) {
    DoxyfileOutput.SetAttribute( "rtf", bVal );
  }
  bVal = m_pConfig->GetGenerateMan();
  if( bVal ) {
    DoxyfileOutput.SetAttribute( "man", bVal );
  }
  bVal = m_pConfig->GetGenerateXML();
  if( bVal ) {
    DoxyfileOutput.SetAttribute( "xml", bVal );
  }
  bVal = m_pConfig->GetGenerateAutogenDef();
  if( bVal ) {
    DoxyfileOutput.SetAttribute( "autogen_def", bVal );
  }
  bVal = m_pConfig->GetGeneratePerlMod();
  if( bVal ) {
    DoxyfileOutput.SetAttribute( "perl_mod", bVal );
  }
  node->InsertEndChild( DoxyfileOutput );
  bVal = m_pConfig->GetEnablePreprocessing();
  if( !bVal ) {
    TiXmlElement DoxyfilePreprocessor( "doxyfile_preprocessor" );
    DoxyfilePreprocessor.SetAttribute( "enable_preprocessing", bVal );
    node->InsertEndChild( DoxyfilePreprocessor );
  }
  TiXmlElement DoxyfileDot( "doxyfile_dot" );
  bVal = m_pConfig->GetClassDiagrams();
  if( bVal ) {
    DoxyfileDot.SetAttribute( "class_diagrams", bVal );
  }
  bVal = m_pConfig->GetHaveDot();
  if( bVal ) {
    DoxyfileDot.SetAttribute( "have_dot", bVal );
  }
  node->InsertEndChild( DoxyfileDot );
  TiXmlElement General( "general" );
  cfg->Write( wxT( "doxyblocks/path_doxygen" ), m_pConfig->GetPathDoxygen() );
  cfg->Write( wxT( "doxyblocks/path_doxywizard" ), m_pConfig->GetPathDoxywizard() );
  cfg->Write( wxT( "doxyblocks/path_hhc" ), m_pConfig->GetPathHHC() );
  cfg->Write( wxT( "doxyblocks/path_dot" ), m_pConfig->GetPathDot() );
  cfg->Write( wxT( "doxyblocks/path_chm_viewer" ), m_pConfig->GetPathCHMViewer() );
  cfg->Write( wxT( "doxyblocks/overwrite_doxyfile" ), m_pConfig->GetOverwriteDoxyfile() );
  cfg->Write( wxT( "doxyblocks/prompt_before_overwriting" ), m_pConfig->GetPromptBeforeOverwriting() );
  bVal = m_pConfig->GetUseAtInTags();
  if( bVal ) {
    General.SetAttribute( "use_at_in_tags", bVal );
  }
  cfg->Write( wxT( "doxyblocks/load_template" ), m_pConfig->GetLoadTemplate() );
  cfg->Write( wxT( "doxyblocks/use_internal_viewer" ), m_pConfig->GetUseInternalViewer() );
  cfg->Write( wxT( "doxyblocks/run_html" ), m_pConfig->GetRunHTML() );
  cfg->Write( wxT( "doxyblocks/run_chm" ), m_pConfig->GetRunCHM() );
  node->InsertEndChild( General );
}


wxString DoxyBlocks::ValidateRelativePath( wxString path ) {
  path.Replace( wxT( "." ), wxT( "" ), true );
  path.Replace( wxT( "~" ), wxT( "" ), true );
  wxFileName fn( path, wxEmptyString );
  path = fn.GetPath( 0 );
  if( path.StartsWith( wxT( "/" ) ) || path.StartsWith( wxT( "\\" ) ) ) {
    path.Remove( 0, 1 );
  }
  return path;
}


void DoxyBlocks::OnTextURL( wxTextUrlEvent& event ) {
  if( event.GetId() == ID_LOG_DOXYBLOCKS && event.GetMouseEvent().ButtonDown( wxMOUSE_BTN_LEFT ) ) {
    m_DoxyBlocksLog->OpenLink( event.GetURLStart(), event.GetURLEnd(), m_pConfig->GetUseInternalViewer() );
  } else {
    event.Skip();
  }
}

void DoxyBlocks::OnWritePrefsTemplate( wxCommandEvent & ( event ) ) {
  DoWritePrefsTemplate();
}


void DoxyBlocks::DoWritePrefsTemplate() {
  if( m_pConfig->WritePrefsTemplate() ) {
    AppendToLog( _( "Settings template saved." ) );
  } else {
    AppendToLog( _( "Error savings settings template." ), LOG_ERROR );
  }
}

void DoxyBlocks::OnReadPrefsTemplate( wxCommandEvent & ( event ) ) {
  DoReadPrefsTemplate();
}


void DoxyBlocks::DoReadPrefsTemplate() {
  if( m_pConfig->ReadPrefsTemplate() ) {
    AppendToLog( _( "Settings template loaded." ) );
  } else {
    AppendToLog( _( "Settings template not found." ), LOG_WARNING );
  }
}


